/*!
 * Rub.js v0.0.1
 * (c) 2018 Co
 * Released under the apache license 2.0
 */

(function (global, factory) {
	typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Rub = factory());
})(this, function () {
	"use strict";
    require("core-js/fn/object/assign")
    require("./ext")
	const html2json = require("html2json").html2json;
	const velement = require("./velement");
	const diff = require("./diff");
	const patch = require("./patch");
    const util = require("./util");
    const env = require("./env");
	const SandBox = require("./sandbox");
	const RubArray = require("./rubArray");

    
	var RUB_LIFE_CYCLE = ["ready", "destroy", "create", "beforeUpdate", "afterUpdate"];
	
	class Rub {
		constructor(opt) {
			this._$debug = opt.debug;
			if (opt.name) {
				this._$rub_name = opt.name;
			}
			if (module.hot) {
				module.hot.dispose(()=>{
					this._$proxyData2View();
				});
			  
				module.hot.accept(()=>{
					this._$proxyData2View();
				});
			}
			this._$init(opt);
			window.onunload = () => {
				this.destroy()
            }
			return this;
		}
        /**
         * 渲染生命周期
         * @param {*} opt 
         */
		_$renderLife(opt) {
			for (var index = 0; index < RUB_LIFE_CYCLE.length; index++) {
				var lifeName = RUB_LIFE_CYCLE[index];
				if (util.isFunction(opt[lifeName])) {
					this[lifeName] = opt[lifeName];
				} else {
					this[lifeName] = () => { };
				}
			}
		}
		/**
		 *
		 * @param {*} opt 框架构建传参
		 * opt={
		 *      el 框架作用域 传入的参数可以为 id 或者 实际元素object
		 * }
		 */
		_$init(opt) {
            //设置节流方法,最多一秒钟60帧
            this._$proxyData2View=util.debounce(this._$proxyData2ViewOrg,15)
			//初始化方法
			this._$setMethod(opt.method);
			//初始化生命周期
			this._$renderLife(opt);
			//初始化数据
			this._$setData(opt.data);
			//初始化计算属性
			this._$setCalcs(opt.calc)
			//设置计算属性
			this._$calcs2Data();
			//初始化监听
			this._$setwatcher(opt.watcher)
			this._$sandBox=new SandBox()
			//调用create方法
			this.create();
			//设置模板挂载dom
			this._$setTemplate(this._$rubEl, opt.template);
			//初始化rub,开始渲染
			var newVnode = this._$renderVNode();
            if (this._$debug ) {
                console.time("init render end");
            }
            this._$setMainEl(opt.el);
            this._$vdom = {};
            this._$renderView(newVnode,false);
            this.ready();
            if (this._$debug ) console.timeEnd("init render end");
		}


        /**
         * 设置计算属性
         * @param {*} methods 方法集
         */
		_$setwatcher(methods) {
			if (!methods) methods = {};
			this._$watcher = {};
			for (var key in methods) {
				if (methods.hasOwnProperty(key)) {
					var method = methods[key];
					this._$watcher[key] = method;
				}
			}
		}

        /**
         * 设置计算属性
         * @param {*} methods 方法集
         */
		_$setCalcs(methods) {
			if (!methods) methods = {};
			this._$calcs = {};
			for (var key in methods) {
				if (methods.hasOwnProperty(key)) {
					var method = methods[key];
					this._$calcs[key] = method;
				}
			}
		}

		/**
		 * 计算属性到数据
		 * 当数据改变时触发
		 */
		_$calcs2Data() {
			for (var key in this._$calcs) {
				if (this._$calcs.hasOwnProperty(key)) {
					var func = this._$calcs[key];
					if (util.isFunction(func)) {
						var result = func.apply(this);//计算结果，如果不为空则放入对应的数据
						if (!util.isUndefined(result) && this.data[key] != result)
							this.data[key] = result
					}
				}
			}
		}

        /**
         * 设置方法
         * @param {*} methods 方法集
         */
		_$setMethod(methods) {
            if (!methods) methods = {};
            this._$method = {};
			for (var key in methods) {
				if (methods.hasOwnProperty(key)) {
                    if(util.isFunction( methods[key])){
                        this._$method[key] =  methods[key];
                        this[key] =  (function(_this,key){             
                            return function(){
                                return methods[key].apply(_this,arguments)
                            };
                        })(this,key) 
                    }
				}
			}
		}



		/**
		 * 设置模板内容
		 * @param {*} template 模板内容
		 */
		_$setTemplate(el, template) {
			if (!template) {
				this._$setError("template can't be null");
			}
			if (!el) el = this._$rubEl;
			template = template.replace(/<!--[\s\S]*?-->/g, ""); //去除html注释
			template = template.replace(/>\s+([^\s<]*)\s+</g, ">$1<").trim(); //去除html标签间的多余空白
			this._$tempateStr = template;
            this._$jsonTemplate = html2json(template);
            this.refs={};
			// if (this._$debug) {
			// 	console.info("dom json  :", this._$jsonTemplate);
			// }
		}

		/**
         * 渲染视图
         * @param {*} el 需要渲染的dom
         * @param {*} flag 重新渲染
         */
		_$renderView(vnode, flag) {
			var el = this._$rubEl;
			if (!el.children.length && flag) {
				return;
			}
            var vdom = this._$traverseTreeDom(vnode);
			var patches = diff(this._$vdom, vdom);
            this._$vdom = vdom;
			if (!this._$rubEl.children[0]) {
				this._$rubEl.innerHTML = "<div></div>"
            }
			patch(this._$rubEl.children[0], patches);
		}
		/**
		 * 解析模板,得到虚拟节点
		 */
		_$renderVNode() {
			//解析所有的节点
			if (this._$jsonTemplate.node == "root" && this._$jsonTemplate.child.length == 1) {
				var vnode = this._$traverseTree(util.copy(this._$jsonTemplate.child[0]),null);
				// if (this._$debug) {
				// 	console.info("vnode :", vnode);
				// }
				return vnode;
			} else {
				this._$setError("template error");
			}
			return null;
		}



		/**
		* 整个虚拟node树遍历
		* @param {*} node
		* @param {*} addData 附加数据,遍历或有局部变量才存在
		*/
		_$traverseTree(node, addData) {
			if (!node) {
				return;
			}
            node = this._$renderNode(node, addData);
            if(node.pif==false){
                return node;
            }
			if (node.child && node.child.length > 0) {
				var i = 0;
                var childs = [];   
				for (i = 0; i < node.child.length; i++) {
                    if(!util.isUndefined(node.childSelected)){
                        node.child[i].childSelected=node.childSelected
                    }
					var xnode = this._$traverseTree(node.child[i], addData)
					if (util.isArray(xnode)) {
						childs = childs.concat(xnode)
					} else if(xnode&&(util.isUndefined(xnode.pif)||(!util.isUndefined(xnode.pif))&&xnode.pif==true)){
						childs.push(xnode)
                    }
                    //如果进行了条件判断,那么给下一个节点信息,告诉他这是连续节点，并且连续答案，一旦有ture那么就一直true
                    if(xnode&&!util.isUndefined(xnode.pif)&&node.child[i+1]){
                        node.child[i+1].conditional=true;
                        node.child[i+1].preresult=xnode.pif||xnode.preresult
                    }
                }
                delete node.childSelected
			}
			node.child = childs
			return node;
		}

		/**
		 * 遍历整个虚拟dom树遍历，包括当前节点
		 * @param {*} node
		 * @param {*} addData 附加数据,遍历或有局部变量才存在
		 */
		_$traverseTreeDom(node) {
			var childEl = [];
			if (node.child && node.child.length > 0) {
				var i = 0;
				for (i = 0; i < node.child.length; i++) {
					if(node.node == "element"&&node.child[i].tag=='block'){
						this._$traverseTreeChildDom(node.child[i].node)
						var eles=this._$traverseTreeChildDom(node.child[i])
						childEl=childEl.concat(eles)
					}else {
						childEl.push(this._$traverseTreeDom(node.child[i]));
					}
				}
            }
			return new velement(this,node.node=='text'?node.node:node.tag , node.node!='text'?node.attr:node.content, childEl, node.events,node.ref);
		}

		/**
		 * 遍历节点不包括当前节点
		 * @param {*} node
		 * @param {*} addData 附加数据,遍历或有局部变量才存在
		 */
		_$traverseTreeChildDom(node){
			var velements = [];
			if (node.child && node.child.length > 0) {
				var i = 0;
				for (i = 0; i < node.child.length; i++) {
					if(node.node == "element"&&node.child[i].tag=='block'){
						var eles=this._$traverseTreeChildDom(node.child[i])
						velements=velements.concat(eles)
					}else {
						velements.push(this._$traverseTreeDom(node.child[i]));
					}
				}
			}
			return velements;
		}
 
		/**
		* 渲染节点包括文字 事件 
		* @param {*} node 需要渲染的节点
		* @param {*} addData 附加数据,遍历或有局部变量才存在
		*/
		_$renderNode(node, addData) {
			if (node.node == 'text'&&util.isUndefined(node.content)) {//正常渲染节点
				node = this._$bindTextView(node, addData)
				return node
			}else if(node.node == 'text'&&!util.isUndefined(node.content)){//提前渲染了下一个节点
                return node;
            }
			if (node.attr) {
                //判断是否带有pif标签
                this._$checkPif(node,addData)
                //设置class
                this._$setClass(node,addData)
                //设置style
                this._$setStyle(node,addData)
                //如果条件不成立那么返回
                if(!util.isUndefined(node.pif)&&node.pif==false)return node;
				for (var key in node.attr) {
                    var val = node.attr[key];
                    //如果是P-show标签那么给节点添加对应属性
                    if (key == 'r-show') { 
                        this._$checkPshow(node,val,addData)
                        delete node.attr[key]
                    }else if (key.indexOf("r-m") != -1) {//如果节点存在数据绑定则绑定数据到 data
                        node = this._$bindRM(key, node, val,addData);
                        delete node.attr[key]
                    }else if (key.indexOf("re-") != -1) {
                        var evenName = key.split("-");
						this._$bindEvent(node, evenName[1], val,addData);
                        delete node.attr[key]
                    }else if (key == 'r-for') {
                        var nodes = this._$rfor(node, val, addData)
                        return nodes;
                    }else if (key.indexOf(":") ==0) {
                        this._$setBindValue(node, key,val, addData)
                    }else if (key == 'ref') {
                        node.ref=val;
                        delete node.attr[key]
                    }
                }
            }
            this._$checkParentSelected(node,addData)
			return node
		}


        /**
         * 如果有父节点选中的情况 ，仅限于select-option 情况
         * @param {*} node 
         * @param {*} addData 
         */
        _$checkParentSelected(node,addData){
            if(!util.isUndefined(node.childSelected)){
                if(node.tag=='option'&&node.attr&&node.attr['value']==node.childSelected){//如果已经有value的情况
                     node.attr['selected']=true;
                    //  delete node.attr['disabled']//如果默认无选择 暂时删除不可选属性
                }else if(node.tag=='option'&&(!node.attr||!node.attr['value'])&&node.child&&node.child.length==1&&node.child[0].node=='text'){//没有value的情况,检查文字，不考虑option下面还有复杂节点情况
                    node.child[0] = this._$bindTextView(node.child[0], addData);
                    if(node.child[0].content==node.childSelected){
                         if(!node.attr)node.attr={}
                        //  delete node.attr['disabled']
                         node.attr['selected']=true;//如果默认无选择 暂时删除不可选属性
                    }
                 }
             }
        }

        /**
         * 设置绑定value
         * @param {*} node 
         * @param {*} val 
         * @param {*} addData 
         */
        _$setBindValue(node, key,val, addData){
            if(/^(input|textarea|option|select|a|img)$/.test(node.tag)){
               var newKey=key.substring(1);
               var result=this._$sandboxRun(val,addData);
               if(/^(disabled|checked|selected|readonly)$/.test(newKey)){
                    if(result)node.attr[newKey]=result
               }else{
                    node.attr[newKey]=result
               }
            }
            delete node.attr[key]
        }
        /**
         * 设置style样式
         * @param {*} node
         * @param {*} addData 
         */
        _$setStyle(node,addData){
            var styleStr='';
            if(node.attr.style){
                if(util.isArray(node.attr.style)){
                    for (var index = 0; index < node.attr.style.length; index++) {
                        var sitem = node.attr.style[index];
                        styleStr+=sitem;
                    }
                    node.attr.style=styleStr
                }else{
                    styleStr=node.attr.style
                }    
            }
            if(node.attr['r-style']){
                if(styleStr!=''){
                    styleStr=' '+styleStr
                }
                if(node.attr['r-style']){
                    if(styleStr!=''){
                        styleStr=styleStr+';'
                    }
                    var val=node.attr['r-style'];
                    if(/\{.+?\}/.test(val)){//对象语法
                        val=val.replace(/^\{/gi,"").replace(/\}$/gi,"")
                        var expressions=val.split(",")
                        for (var index = 0; index < expressions.length; index++) {
                            var expression = expressions[index];
                            if(/^.+?\:.+?$/.test(expression)){
								var tempArr=expression.split(":")
								if(/(^\'.+?\'$)|(^\".+?\"$)/.test(tempArr[1])){
									var newVal=util.removeSideSymbol(tempArr[1])
									if(newVal)
										styleStr+=tempArr[0]+":"+newVal+";";
								}else{
									var styleResult=this._$sandboxRun(tempArr[1],addData);
									if(styleResult&&util.isString(styleResult)){
										styleStr+=tempArr[0]+":"+styleResult+";";
									}
								}
                            }
                        }
                        node.attr['style']=styleStr
                    }else if(/\[.+?\]/.test(val)){//数组语法
						val=val.replace(/^\[/gi,"").replace(/\]$/gi,"")
						var expressions=val.split(",")
						for (var index = 0; index < expressions.length; index++) {
							var expression = expressions[index];
							var result=this.data[expression];
							if(result){
								if(util.isString(result)){
									styleStr+=result+";";
								}else if(util.isObject(result)){
									styleStr+=this._$getStyleStrByObj(result);
								}
							}else if(/(^\'.+?\'$)|(^\".+?\"$)/.test(expression)&&util.isString(expression)){
								expression=util.removeSideSymbol(expression);
								styleStr+=expression+";";
							}
						}
						node.attr['style']=styleStr
					}else if(util.isString(val)){
						var result=this.data[val];
						if(result){
							if(util.isString(result)){
								styleStr+=result+";";
							}else if(util.isObject(result)){
								styleStr+=this._$getStyleStrByObj(result);
							}
						}
						node.attr['style']=styleStr
					}
                    delete node.attr['r-style'];
                }
            }
        }

        /**
         * 通过对象得到style string
         * @param {*} obj 
         */
        _$getStyleStrByObj(obj){
            var styleStr=''
            if(util.isObject(obj)){
                for (var key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        var val = obj[key];
                        styleStr+=`${key}:${val};`
                    }
                }
            }
            return styleStr
        }

        /**
         * 设置class样式
         * @param {*} node
         * @param {*} addData 
         */
        _$setClass(node,addData){
            var classStr='';
            if(node.attr.class){
                if(util.isArray(node.attr.class)){
                    for (var index = 0; index < node.attr.class.length; index++) {
                        var citem = node.attr.class[index];
                        classStr+=" "+citem
                    }
                    if(classStr.length>0){
                        classStr=classStr.substring(1)
                    }
                    node.attr.class=classStr
                }else{
                    classStr= node.attr.class
                }
               
            }
            if(node.attr['r-class']){
                if(classStr!=''){
                    classStr=' '+classStr
                }
				var val=node.attr['r-class'];
                if(/\{.+?\}/.test(val)){//对象语法
                    val=val.replace(/^\{/gi,"").replace(/\}$/gi,"")
                    var expressions=val.split(",")
                    for (var index = 0; index < expressions.length; index++) {
                        var expression = expressions[index];
                        if(/^.+?\:.+?$/.test(expression)){
                            var tempArr=expression.split(":")
                            if(this._$sandboxRun(tempArr[1],addData)){
                                classStr+=" "+tempArr[0]
                            }
                        }else{
                            var result=this._$sandboxRun(expression,addData);
                            if(result){
                                classStr+=" "+result
                            }
                        }
                    }
                    if(classStr.length>0){
                        classStr=classStr.substring(1)
                    }
                    node.attr.class=classStr
                }else if(/\[.+?\]/.test(val)){//数组语法
                    val=val.replace(/^\[/gi,"").replace(/\]$/gi,"")
                    var expressions=val.split(",")
                    for (var index = 0; index < expressions.length; index++) {
                        var expression = expressions[index];
                        var result=this._$sandboxRun(expression,addData);
                        if(result){
                            classStr+=" "+result
                        }
                    }
                    if(classStr.length>0){
                        classStr=classStr.substring(1)
                    }
                    node.attr.class=classStr
                }
                delete node.attr['r-class'];
            }
        }


        /**
         * r-show判断,去除或者加上display:none;
         * @param {*} node 
         * @param {*} val 
         * @param {*} addData 
         */
        _$checkPshow(node,val,addData){
            var nodeStyle=!node.attr.style?"":node.attr.style;
            if(nodeStyle!=''){
                // var regE = /\{\{(.+?)\}\}/g;
                nodeStyle=nodeStyle.replace(/display\:.+?\;/g,"")
            }
            if(!this._$sandboxRun(val,addData)){
                nodeStyle="display:none;"+nodeStyle
            }

            node.attr.style=nodeStyle;
        }

        /**
         * 检查是否带有r-if标签，并且判断条件是否成立
         * 如果还处于连续判断中 且前面所有判断不能为true
         * @param {*} node 当前节点
		 * @param {Object} addData 附加数据
         */
        _$checkPif(node,addData){
            var val;
            if(node.attr){
                if (node.attr['r-if']) {
                    val = node.attr['r-if'];
                    if(this._$sandboxRun(val,addData)){
                        node.pif=true;
                        node.preresult=true;
                        delete node.attr['r-if']
                    }else{
                        node.pif=false;
                        return node;
                    }
                }else if (node.attr['r-elif']&&node.conditional) {
                    val = node.attr['r-elif'];
                    if(node.preresult!=true&&this._$sandboxRun(val,addData)){
                        node.pif=true;
                        delete node.attr['r-elif']
                    }else{
                        node.pif=false;
                        return node;
                    }      
                }else if (node.attr['r-else']==''&&node.conditional) {
                    if(node.preresult!=true){
                        node.pif=true;
                        delete node.attr['r-else']
                    }else{
                        node.pif=false;
                        return node;
                    }      
                }
            }
            return node;
        }


		/**
		 * 遇到循环标签,那么递归复制创建节点组
		 * @param {*} node 
		 * @param {*} val 
		 * @param {*} addData 附加数据,遍历或有局部变量才存在
		 */
		_$rfor(node, val, addData) {
			delete node.attr['r-for']
			var elArr = [];
			var data;
			if (val.indexOf("in") != -1) {    
                data =this._$getDataVal(this.data,addData,val[2]).value
				if (val[0] && data && util.isArray(data)) {
					var kvarr = val[0].split(",")
					var keyName = kvarr[0].replace("(")
					var indexName = kvarr[1] ? kvarr[1].replace(")") : 'index';
					if (addData && (!util.isUndefined(addData[keyName]) || !util.isUndefined(addData[indexName]))) {
						this._$setError("key already exists")
					}
					for (var index = 0; index < data.length; index++) {
						var itemData = Object.create({});//单个节点的数据
						itemData[keyName] = data[index]
						itemData[indexName] = index
						if (addData) itemData = Object.assign(itemData, addData)
						var nnode;
						nnode = util.copy(node);//克隆节点
						elArr.push(this._$traverseTree(nnode, itemData))
					}
				} else {
					this._$setError("error r-for params")
				}
			} else {        
                data =this._$getDataVal(this.data,addData,val).value
				if (data && util.isArray(data)) {
					if (addData && (!util.isUndefined(addData.item) || !util.isUndefined(addData.index))) {
						this._$setError("key already exists")
					}
					for (var index = 0; index < data.length; index++) {
						var itemData = { item: data[index], index: index };//单个节点的数据
                        if (addData) itemData = Object.assign(itemData, addData)
						var nnode;
						nnode = util.copy(node);//克隆节点
						elArr.push(this._$traverseTree(nnode, itemData))
					}
				} else {
					this._$setError("error r-for params")
				}
			}

			return elArr;
		}

        /**
         * 从Proxy 中取出一个object对象
         * @param {*} object 
         */
		_$getCompleteObj(object) {
			var tempObj = {}
			for (var key in object) {
				if (object.hasOwnProperty(key)) {
					var element = object[key];
					if (util.isObject(element)) {
						tempObj[key] = this._$getCompleteObj(element)
					} else {
						tempObj[key] = element
					}
				}
			}
			return tempObj;
		}


        /**
         * 遍历代理对象
         * @param {*} obj 
         */
		_$proxyObj(object, mkey, prefix,sumKey) {
			if(!sumKey){
				sumKey=mkey
			}else{
				sumKey+="."+prefix;	
			}
			var _this = this;
			for (var key in object) {
				if (object.hasOwnProperty(key)) {
					var item = object[key];
					if (util.isArray(item)) {
						object[key] = this._$proxyObj(item, key, key,sumKey)
					} else if (util.isObject(item)) {
						object[key] = this._$proxyObj(item, key, key,sumKey)
					}
				}
			}
			function getProxy(mkey,sumKey) {
				return new Proxy(object, {
					defineProperty(target, property, descriptor) {
                        _this._$proxyData2View();
						return Reflect.defineProperty(target, property, descriptor);
					},
					get(target, property) {
						if (property in target) {
							return target[property];
						} else {
							return null;
						}
					},
					set(target, key, value, receiver) {
                        //如果这是个计算属性变化,因为已经计算过，所以直接赋值，不需要循环计算
                        if(util.isFunction(_this._$calcs[key])){
                            target[key] = value
                            return true;
                        }
						//如果对象被重置了,那么重新设置代理
						if (util.isArray(value) || (util.isObject(target) && util.isObject(value))) {
							var oldObj;
							if (_this._$watcher && util.isFunction(_this._$watcher[(sumKey+"."+key)])) {
								if (util.isArray(value)) {
									oldObj = util.copyArr(_this.data[key])
								} else {
									oldObj = _this._$getCompleteObj(_this.data[key])
								}
							}
							var newProObj = _this._$proxyObj(value, key)
							var res = Reflect.set(target, key, newProObj, receiver);
                            _this._$proxyData2View();
							//查看是否有watcher
							if (_this._$watcher && util.isFunction(_this._$watcher[(sumKey+"."+key)])) {
								_this._$watcher[(sumKey+"."+key)](value, oldObj)
							}
							return res;
                        } else if (util.isArray(target)) {//如果是数组 push splice
							var oldObj;
							if (_this._$watcher && util.isFunction(_this._$watcher[sumKey])) {
								oldObj = util.copyArr(_this.data[mkey])
							}
							var res = Reflect.set(target, key, value, receiver);
							//查看是否有watcher
							if (_this._$watcher && util.isFunction(_this._$watcher[sumKey])) {
								var newVal = _this.data[mkey]
								_this._$watcher[sumKey](newVal, oldObj)
							}
							_this._$proxyData2View();
							return res;
						} else {
							//查看是否有watcher
                            if ( _this._$watcher && util.isFunction(_this._$watcher[(sumKey+"."+key)])) {
                                _this._$watcher[sumKey+"."+key](value, target[key])
                            }
                            target[key] = value
                            _this._$proxyData2View();
                            return true;
						}
					}
				});
			}
			return getProxy(mkey,sumKey)
		}


		getProxy(obj,nvalue,sumKey,key) {
            let initFlag=false;
			let _this = this;
            // 如果这是个计算属性变化,因为已经计算过，所以直接赋值，不需要循环计算
            if(_this._$calcs&&util.isFunction(_this._$calcs[key])){
                return;
            }
			Object.defineProperty(obj, key, {
				configurable:true,
				enumerable: true,
				set: function(newValue) {
                    //如果重新放入的是一个对象，不管是object 或者Array
                    let change=false;
					if(util.isObject(newValue)){
                        if(_this._$origin_data[sumKey]&&JSON.stringify(newValue)===JSON.stringify(_this._$origin_data[sumKey]))return;
						//查看是否有watcher
						if (initFlag&&_this._$watcher && util.isFunction(_this._$watcher[sumKey])) {	
							_this._$watcher[sumKey].call(_this,newValue,util.copy(_this._$origin_data[sumKey]))
						}
						//优先解决先重设值
						if(_this._$dataSet&&initFlag){
							_this._$origin_data[sumKey]=null;
							_this._$setObjDefined(obj,newValue,sumKey,key)
						}else{
                            _this._$origin_data[sumKey]=newValue;
                            change=true;
						}
					}else if(util.isArray(newValue)){
                        if(_this._$origin_data[sumKey]&&newValue.equals(_this._$origin_data[sumKey]))return;
						//查看是否有watcher
						if (initFlag&&_this._$watcher && util.isFunction(_this._$watcher[sumKey])) {	
							_this._$watcher[sumKey].call(_this,newValue,util.copyArr(_this._$origin_data[sumKey]))
						}
						if(_this._$dataSet&&initFlag){
							_this._$origin_data[sumKey]=null;
							_this._$setObjDefined(obj,newValue,sumKey,key)
						}else{
							var rubArr=new RubArray((oldArr)=>{
                                //查看是否有watcher
                                if (_this._$watcher && util.isFunction(_this._$watcher[sumKey])) {	
                                    _this._$watcher[sumKey].call(_this,_this._$origin_data[sumKey],oldArr)
                                }
								_this._$proxyData2View();
							},newValue)
                            _this._$origin_data[sumKey]=rubArr;
                            change=true;
						}
					}else{
                        if(_this._$origin_data[sumKey]===newValue)return;
						//查看是否有watcher
						if (initFlag&&_this._$watcher && util.isFunction(_this._$watcher[sumKey])) {	
							_this._$watcher[sumKey].call(_this,newValue,_this._$origin_data[sumKey])
                        }
                        change=true;
						_this._$origin_data[sumKey]=newValue;
					}
					change&&_this._$proxyData2View();
				},
				get(){
					return _this._$origin_data[sumKey];
				}
			});
			obj[key]=nvalue
			initFlag=true;
		}
		 /**
          * 遍历代理对象
          * @param {*} pobject 需要代理的对象
          * @param {*} object 
          * @param {*} sumKey 
          * @param {*} key 
          */
		_$setObjDefined(pobject,object,sumKey,key) {
			//如果对象，遍历对象
			if(util.isObject(object)){
				for (var subkey in object) {
					if (object.hasOwnProperty(subkey)) {
						var item = object[subkey];
						if (util.isObject(item)) {
							this._$setObjDefined(object,item,sumKey+"."+subkey,subkey)
						}if (util.isArray(item)) {
							this._$setObjDefined(object,item,sumKey+"."+subkey,subkey)
						}else{
							this.getProxy(object,item,sumKey+"."+subkey,subkey)
						}
					}
				}
			}else if(util.isArray(object)){
				for (let index = 0; index < object.length; index++) {
					const item = object[index];
					this._$setObjDefined(object,item,sumKey+"."+index,index)
				}
			}
			this.getProxy(pobject,object,sumKey,key)
		}

		/**
		 * 设置数据源
		 * @param {*} data
		 */
		_$setData(data) {
			if (!data) {
				data = {}
			}
			// if (util.isObject(data)&&window.Proxy) {
			// 	this.data = this._$proxyObj(data, 'data')
			// }else{
                //低版本浏览器兼容
				this.data={};
				this._$dataSet=false
				this._$origin_data={};
				this._$setObjDefined(this,data,"data","data")
				this._$dataSet=true;
			// }
		}


		/**
		 * 代理数据到识图操作
		 */
		_$proxyData2ViewOrg() {
			if (this._$rubEl) {
				//重新计算计算方法
				this._$calcs2Data();
				this.beforeUpdate(this._$rubEl.children[0].vdom)
				var newNode = this._$renderVNode();
				this._$renderView(newNode, true);
				this.afterUpdate(this._$rubEl.children[0].vdom)
			}
		}

		//设置作用域
		_$setMainEl(el) {
			if (!el) {
				this._$setError("Wrong element");
			}
			if (util.isString(el)) {
				this._$rubEl = document.getElementById(el); //元素
			} else if (util.isObject(el)) {
				this._$rubEl = el;
			} else {
				this._$setError("Wrong element");
			}
		}


		/**
         * 绑定 数据 和 视图
         * @param {*} event 
         * @param {*} node 
         * @param {*} val 
         */
		_$bindRM(event, node, val,addData) {
			//如果没有这个data对象,不进行绑定
			// if (util.isUndefined(this.data[val])&&util.isUndefined(addData)) {
			// 	return node;
            // }
            var result=this._$getDataVal(this.data,addData,val);
            
            var dataVal=result.value;
            var addFlag=result.flag;
			var arr = event.split(".");
			var suffix = "";
			if (arr.length > 1) {
				suffix = arr[1];
            }
            if (!node.events) node.events = {};
            var listenEvent = ['input', 'blur'];
            if(/^(input|textarea)$/.test(node.tag)&&!/^(checkbox|radio)$/.test(node.attr.type)){
                node.attr['value'] = dataVal;
            }
            if(/^(select)$/.test(node.tag)){
                if(node.attr&&!util.isUndefined(node.attr['multiple'])){
                    if(env.isAndroid||env.isIOS){
                        listenEvent=['change'];
                    }else{
                        listenEvent=['click'];
                    }
                }else{
                    node.attr['value'] = dataVal;
                    node.childSelected=dataVal;
                }
            }
            if(/^(checkbox|radio)$/.test(node.attr.type)){
                if(node.attr.type=='checkbox'){
                    //如果是数组
                    if(util.isArray(dataVal)){
                        if(dataVal.indexOf(node.attr['value'])!=-1){
                            node.attr['checked']=true;
                        }
                    }else if(util.isBoolean(dataVal)){
                        node.attr['checked'] = dataVal;
                    }
                }else{
                    if(util.isString(dataVal)&&dataVal==node.attr['value']){
                        node.attr['checked'] = true;
                    }else if(util.isString(dataVal)&&dataVal==node.attr['value']){
                        node.attr['checked'] = false;
                    }
                }
                listenEvent=['click'];
            }
			for (var index = 0; index < listenEvent.length; index++) {
				var event = listenEvent[index];
				if(!node.events[event])node.events[event] ={func:[], flag: false}
				node.events[event].func.push(
					e => {
                        var target=e.target;
                        if(e.target.tagName=='OPTION'){
                            if(e.target.parentNode.tagName=='OPTGROUP'){
                                target=e.target.parentNode.parentNode;
                            }else if(e.target.parentNode.tagName=='SELECT'){
                                target=e.target.parentNode;
                            }
                        }
                        var typeName =  target.type || "";
                        var value = target.value;
                        result=this._$getDataVal(this.data,addData,val);
                        dataVal=result.value;
                        addFlag=result.flag;
                        if(typeName=='checkbox'){
                            if(util.isArray(dataVal)){
                                //如果选中
                                if(target.checked){
                                    dataVal.push(target.value)
                                }else{//如果取消选中
                                    var position=dataVal.indexOf(target.value)
                                    dataVal.splice(position,1)
                                }
                            }else if(util.isBoolean(dataVal)){
                                value =e.target.checked;
                                this._$setDataVal(this.data,addData,val,value)
                                if(addFlag){
                                    this._$proxyData2View();
                                }
                            }
                        }else if(typeName=='select-multiple'){
                            if(e.target.tagName=='OPTION'||env.isIOS||env.isAndroid||(env.isIE&&e.target.tagName=='SELECT')){
                                var newArr=[];
                                if(util.isArray(dataVal))newArr=dataVal;
                                this._$setDataVal(this.data,addData,val,this._$getAllSelectNode(target,newArr))
                                if(addFlag){
                                    this._$proxyData2View();
                                }
                            }
                        }else if (value !== dataVal) {
                            this._$setDataVal(this.data,addData,val,value)
                            if(addFlag){
                                this._$proxyData2View();
                            }
                        }
						if (suffix == "stop") {
							e.stopPropagation();
						} else if (suffix == "prevent") {
							e.preventDefault();
						}
					}
				)
			}
			return node;
		}


        /**
         * 设置值
         */
        _$setDataVal(data,addData,key,val){
            if(/\w\.\w/.test(key)){
               if(!this._$setObjDataByName(key,addData,val)){
                    this._$setObjDataByName(key,data,val);
               }
            }else{
                //如果有附加数据且有对应值
                if(addData){
                    addData[key]=val
                }else{
                    data[key]=val 
                }
            }
        }

        /**
         * 拿到值
         */
        _$getDataVal(data,addData,key){
            var dataVal;
            var flag=false;
            if(/\w\.\w/.test(key)){
               var dataVal=this._$getObjDataByName(key,addData);
               if(!util.isUndefined(dataVal)){
                    flag=true;  
               }else if(util.isUndefined(dataVal)&&data){
                    dataVal=this._$getObjDataByName(key,data);
               }
            }else{
                if(addData&&!util.isUndefined(addData[key])){
                    dataVal=addData[key];
                    flag=true;
                }else if(data&&!util.isUndefined(data[key])){
                    dataVal=data[key];
                }
            }
            if(util.isUndefined(dataVal))dataVal="";
            return {value:dataVal,flag:flag}
        }

        /**
         * 得到所有选中节点
         * @param {*} node 
         */
        _$getAllSelectNode(node,oldArr){
            var newArr=[];
            for (var index = node.length-1; index >=0; index--) {
                var item = node[index];
                if(item.selected){
                    if(oldArr.indexOf(item.value)!=-1){//已存在放前面
                        newArr.unshift(item.value)
                    }else{
                        newArr.push(item.value)
                    }
                }
            }
            return newArr;
        }
        

        /**
         * 绑定事件
         * @param {*} node 
         * @param {*} event 
         * @param {*} value 
         */
		_$bindEvent(node, event, value,addData) {
			var arr = event.split(".");
			var eventName = arr[0];
			var suffix = "";
			if (arr.length > 1) {
				suffix = arr[1];
			}
			if (!node.events) node.events = {};
			var _this = this;
			if(!node.events[eventName])node.events[eventName] ={func:[], flag: false}
			node.events[eventName].func.push(
				(...params) => {
					var result = _this._$searchParameter(value,addData);
					var val = result[0]
                    var _querys = result[1]
					if (util.isFunction(_this._$method[val])) {
						// this.method[value]();//调用方法
                        _querys = _querys.concat(params)
						_this._$method[val].apply(_this,_querys);
                    }
                    if(result[3]&&_querys.length>0){
                        _this._$proxyData2View();
                    }
					var e = params[0];
					if (suffix == "stop") {
						e.stopPropagation();
					} else if (suffix == "prevent") {
						e.preventDefault();
					}
				}
            );    
			return node
		}

		/**
		 * 检索参数
		 * @param {*} value 
		 */
		_$searchParameter(value,addData) {
            var _querys = [];
            var addFlag=false;
			//判断是否有参数
			if (value.indexOf("(") != -1 || value.indexOf(")") != -1) {
				if (value.indexOf("(") != -1 && value.indexOf(")") != -1) {
					var tempQueryStr = value.substring(value.indexOf("(") + 1, value.indexOf(")"))
					if (tempQueryStr) {
						_querys = tempQueryStr.split(",")
					}
					for (var index = 0; index < _querys.length; index++) {
						var query = _querys[index];
						if (!isNaN(parseFloat(query))) {
							_querys[index] = parseFloat(query) * 1;
							continue
						}
						//如果是string
						if (util.isString(query)) {
							if (query.indexOf("'") != -1 || query.indexOf('"') != -1) {
								if ((query.indexOf("'") == 0 && query.indexOf("'", 2) == query.length - 1) || (query.indexOf('"') == 0 && query.indexOf('"', 2) == query.length - 1)) {
									query = query.replace(/^\"|\"$/g, '');
									query = query.replace(/^\'|\'$/g, '');
									_querys[index] = query
								} else {
									this._$setError("error method params")
								}
							} else {//如果是取data的参数
                                let tempResult=this._$getDataVal(this.data,addData,query)
                                _querys[index]=tempResult.value;
                                if(!addFlag){
                                    addFlag=tempResult.flag
                                }
								if (util.isUndefined(_querys[index])) {
									this._$setError("method params not found")
								}
							}
						}
					}
					value = value.substr(0, value.indexOf("("))
				} else {
					_this._$setError("error method")
				}
			}
			return [value, _querys,addFlag]
		}

		/**
		 * 根据方法名拿到参数
		 * @param {*} methodName 
		 */
		_$getObjDataByName(methodName,data) {
			var array = methodName.split(".")
			var obj ;
			if(data){
				obj =data[array[0]];
			}else{
				obj =this.data[array[0]];
			}
			
			if (!obj) return;
			for (var index = 1; index < array.length; index++) {
				var key = array[index];
				obj = obj[key]
				if (util.isUndefined(obj) && (array.length - 1) == index) {
					obj = '';
					break;
				}
			}
			if (!obj && obj != '') obj = undefined
			return obj;
        }
        
        /**
		 * 根据方法名拿到参数
		 * @param {*} methodName 
		 */
		_$setObjDataByName(methodName,data,val) {
			var array = methodName.split(".")
			var obj ;
			if(data){
				obj =data[array[0]];
			}else{
				obj =this.data[array[0]];
			}
			
			if (!obj) return;
			for (var index = 1; index < array.length; index++) {
                var key = array[index];
                if ( (array.length - 1) == index) {
                    obj[key]=val
                    return true;
				}
				obj = obj[key]
				if(util.isUndefined(obj[key]))break;
			}
            return false
		}
		/**
         * 处理节点中的 data-view
         * @param {*} node 需要渲染的文字节点
		 * @param {*} addData 附加数据,遍历或有局部变量才存在
         */
		_$bindTextView(node, addData) {
			var content = node.text;
            var array = util.getMathCharacter(content)
			var diffLen=0;
			for (var index = 0; index < array.length; index++) {
				var item = array[index].text;
				var leftPostion = array[index].left;
				var len = array[index].len;
				// item = item.replace("{{", "").replace("}}", "")	
				if (addData && !util.isUndefined(addData[item])&&item.indexOf(".") == -1) {
					var newItem = util.toString(addData[item]);
					if(!util.isUndefined(newItem)){
						content = util.plusXing(content,leftPostion-diffLen,len,newItem);
						diffLen+=item.length-newItem.length+4
					}
				} else if (addData &&item.indexOf(".") != -1) {
					var newItem = this._$getObjDataByName(item,addData)
					if(!util.isUndefined(newItem)){
						newItem=util.toString(newItem)
						content = util.plusXing(content,leftPostion-diffLen,len,newItem);
						diffLen+=item.length-newItem.length+4
					}
					
				}else if (!addData&&item.indexOf(".") != -1) {//如果是一个复杂对象
					var newItem = util.toString(this._$getObjDataByName(item))
					if(!util.isUndefined(newItem)){
						newItem=util.toString(newItem)
						content = util.plusXing(content,leftPostion-diffLen,len,newItem);
						diffLen+=item.length-newItem.length+4
					}
				}else if (this.data.hasOwnProperty(item)) {//第一种情况是data
					var newItem = util.toString(this.data[item]);
					if(!util.isUndefined(newItem)){
						content = util.plusXing(content,leftPostion-diffLen,len,newItem);
						diffLen+=item.length-newItem.length+4
					}
				}else if (item.indexOf("=") != -1 || item.indexOf("+") != -1 ||
					item.indexOf("*") != -1 || item.indexOf("/") != -1 ||
					item.indexOf("%") != -1 || item.indexOf("+") != -1 ||
					item.indexOf("-") != -1 || item.indexOf(" ") != -1) {
					try {
						var nitem=item.replace(/(^\s*)|(\s*$)/g,"")
						if(nitem.length&&((nitem[0]=="\""&&nitem[nitem.length-1]=="\"")||(nitem[0]=="'"&&nitem[nitem.length-1]=="'"))){
							continue;
						}
						var newItem=this._$sandboxRun(item)
						if(!util.isUndefined(newItem)){
							newItem=util.toString(newItem)
							content = util.plusXing(content,leftPostion-diffLen,len,newItem);
							diffLen+=item.length-newItem.length+4
						}
					} catch (e) { this._$setError(e) }
				} 
			}
			node.content = content;
			return node;
		}


        /**
         * 沙盒运行
         * @param {*} jsCode 沙盒运行代码
		 * @param {*} addData 附加数据
         */
		_$sandboxRun(jsCode,addData) {
            try{
                var result=this._$sandBox.run(jsCode,this.data,this._$method,addData);
                return result;
            }catch(e){
                if(this._$debug==2)
                     console.warn(e)
                return false;
            }
		}

		/**
		 * 抛出框架错误
		 * @param {*} str 错误信息
		 */
		_$setError(str) {
			if(this._$debug)
				throw new Error(str);
			else
				console.warn(str)
		}
		/**根据id拿到模板字符串 */
		static getTemplate(id){
			var dom=document.getElementById(id);
			var domHtml=dom.outerHTML;
			dom.remove();
			return  domHtml;
		}
	}
	if(env.inBrowser)window.Rub=Rub
	
	return Rub;
});
